<?php

namespace app\third\model;

use think\facade\Db;

class Movie
{
    /**
     * 创建订单
     */
    public function createOrder($params)
    {
        $fields = [
            'out_order_id', 'show_id', 'mobile', 'seats', 'notify_url',
        ];
        foreach ($fields as $field) {
            if (empty($params[$field])) {
                return fail('缺少参数 ' . $field, CODE_MISS_PARAM);
            }
        }
        if (!checkMobile($params['mobile'])) {
            return fail('手机号码格式有误', CODE_MOBILE_ERROR);
        }

        $agentId = $params['agent']['id'];
        // 代理商返佣比例
        $commissionRate = $params['agentServiceConfig']['value'];
        if ($commissionRate < 0) {
            $commissionRate = 0;
        } elseif ($commissionRate > 100) {
            $commissionRate = 100;
        }

        // 获取供应商
        $supplierIds = Db::name('agent_supplier')
            ->where('agent_id', $agentId)
            ->where('serv_type', PRODUCT_FILM_SERV)
            ->column('supplier_id');
        if (empty($supplierIds)) {
            return fail('通道维护中');
        }
        $supplier = Db::name('base_supplier')
            ->field('id, settle_value')
            ->whereIn('id', $supplierIds)
            ->where('serv_type', PRODUCT_FILM_SERV)
            ->whereNull('deleted_at')
            ->select()
            ->toArray();
        if (empty($supplier)) {
            return fail('通道维护中。');
        }
        // 随机搞一个供应商
        $index = array_rand($supplier);
        $supplier = $supplier[$index];

        if (empty($params['show_id'])) {
            return fail('场次 id 不能为空');
        }
        if (empty($params['mobile'])) {
            return fail('请填写手机号');
        }
        $show = Db::name('taototo_schedule')
            ->where('show_id', $params['show_id'])
            ->order('id desc')
            ->find();
        if (empty($show)) {
            return fail('场次id已过期，请刷新重试');
        }
        $film = Db::name('taototo_film')
            ->field('pic')
            ->where('film_id', $show['film_id'])
            ->find();

        $netPrice = $show['net_price'];

        // 折扣
        $discount = Db::name('taototo_cinema')
            ->where('cinema_id', $show['cinema_id'])
            ->value('down_discount_rate');
        if (empty($discount)) {
            $discount = 1.0;
        }
        $taototo = new \app\common\service\Taototo;
        $areaPrice = $taototo->getScheduleAreaPriceArr($show['schedule_area']);

        if (empty($params['seats'])) {
            return fail('请选择座位');
        }
        $seats = $params['seats'];
        unset($params['seats']);
        $totalNetPrice = 0;
        $seat = [];
        $seatId = [];
        $seatNo = [];
        $orderNum = 0;
        foreach ($seats as $k => $v) {
            if (isset($v['area']) && isset($areaPrice[$v['area']]['price'])) {
                $price = $areaPrice[$v['area']]['price'];
            } else {
                $price = $netPrice;
            }
            if ($price <= 0) {
                return fail('座位价格有误，请刷新重试');
            }
            $seats[$k]['netPrice'] = $price;
            $totalNetPrice += $price;
            if (!empty($v['lovestatus'])) {
                $seat[] = $v['seatNo'] . '(情侣座)';
            } else {
                $seat[] = $v['seatNo'];
            }
            $seatId[] = $v['seatId'];
            $seatNo[] = $v['seatNo'];
            $orderNum += 1;
        }
        $salePrice = intval(strval($totalNetPrice * $discount));
        if ($salePrice <= 0) {
            return fail('订单价格有误，请刷新重试');
        }

        $orderId = $this->generateOrderId();
        if (false === $orderId) {
            return fail('订单号生成失败，请刷新重试');
        }

        $taototoOrderParams = [
            'showId' => $params['show_id'],
            'seat' => implode(',', $seat),
            'reservedPhone' => $params['mobile'],
            'thirdOrderId' => $orderId,
            'notifyUrl' => env('app.api_url') . '/api/notify_v2/taototo',
            'acceptChangeSeat' => $params['accept_change_seat'] ?? 0,
            'seatId' => implode('|', $seatId),
            'seatNo' => implode('|', $seatNo),
        ];
        unset($seat);
        unset($seatId);
        unset($seatNo);

        $order = Db::name('movie_order')
            ->field('id')
            ->where('out_order_id', $params['out_order_id'])
            ->where('agent_id', $agentId)
            ->find();
        if (!empty($order)) {
            return fail('订单已存在', CODE_ORDER_EXISTS);
        }
        if (mb_strlen($params['out_order_id']) > 32) {
            return fail('out_order_id 不能超过 32 个字符', CODE_ERROR);
        }
        if (mb_strlen($params['notify_url']) > 100) {
            return fail('notify_url 不能超过 100 个字符', CODE_ERROR);
        }

        Db::startTrans();
        try {
            $balance = Db::name('agent')
                ->where('id', $agentId)
                ->value('balance');

            if ($balance < $salePrice) {
                Db::rollback();
                return fail('账户余额不足，请及时充值', CODE_LACK_OF_BALANCE);
            }
            $res = Db::name('agent')
                ->where('id', $agentId)
                ->where('balance', '>=', $salePrice)
                ->dec('balance', $salePrice)
                ->update([
                    'balance_last_updated_at' => date('Y-m-d H:i:s'),
                ]);
            if (!$res) {
                Db::rollback();

                return fail('账户余额不足，请及时充值。' . __LINE__, CODE_LACK_OF_BALANCE);
            }

            $id = Db::name('movie_order')->insertGetId([
                'agent_id' => $agentId,
                'settle_type' => $params['settle_type'],
                'order_id' => $orderId,
                'supplier_order_id' => '',
                'film_id' => $show['film_id'],
                'film_image' => $film['pic'] ?? '',
                'film_name' => $show['film_name'],
                'show_time' => $show['show_time'],
                'end_time' => $show['end_time'],
                'hall_name' => $show['hall_name'],
                'duration' => $show['duration'],
                'seats_str' => $taototoOrderParams['seat'],
                'cinema_id' => $show['cinema_id'],
                'cinema_name' => $show['cinema_name'],
                'accept_change_seat' => $taototoOrderParams['acceptChangeSeat'],
                'mobile' => $params['mobile'],
                'status' => 2,
                'order_num' => $orderNum,
                'total_net_price' => $totalNetPrice,
                'commission_rate' => $commissionRate,    // 代理商返佣比例
                'sale_price' => $salePrice, // 销售价
                'real_seat' => '',
                'ticket_code' => '[]',
                'ticket_image' => '[]',
                'settle_time' => 0,
                'supplier_id' => $supplier['id'],
                'out_order_id' => $params['out_order_id'],
                'notify_url' => $params['notify_url'],
                'order_from' => ORDER_FROM_API,
                'plan_type' => $show['plan_type'],
            ]);
            Db::name('taototo_order')
                ->insert([
                    'agent_id' => $agentId,
                    'order_id' => $orderId,
                    'params' => json_encode($taototoOrderParams, JSON_UNESCAPED_UNICODE),
                    'status' => 2,
                    'result' => '',
                ]);
            Db::name('base_supplier')
                ->where('id', $supplier['id'])
                ->inc('order_count', 1)
                ->update();
            Db::name('agent_balance_log')
                ->insert([
                    'agent_id' => $agentId,
                    'type' => BALANCE_FILM_EXPENSE,
                    'amount' => -$salePrice,
                    'old_balance' => $balance,
                    'new_balance' => $balance - $salePrice,
                    'remark' => '购买影票：' . $show['film_name'] .  '，销售价：' . fen2yuan($salePrice) . '元。订单号：' . $orderId,
                    'quote_id' => $id,
                    'trade_no' => $orderId,
                ]);

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            return fail('下单失败：' . $e->getMessage() . $e->getLine());
        }

        return success('下单成功', [
            'order_id' => $orderId,
            'sale_price' => $salePrice,
        ]);
    }

    /**
     * 订单查询.
     */
    public function queryOrder($params)
    {
        if (empty($params['out_order_id'])) {
            return fail('缺少参数 out_order_id', CODE_MISS_PARAM);
        }

        $order = Db::name('movie_order')
            ->field('order_id, out_order_id, sale_price, profit, close_cause,
            supplier_status as status, ticket_code, ticket_image, real_seat,
            film_id, film_image, film_name, show_time, duration, end_time, hall_name,
            cinema_id, cinema_name, mobile, accept_change_seat, order_num, total_net_price')
            ->where('out_order_id', $params['out_order_id'])
            ->where('agent_id', $params['agent']['id'])
            ->find();
        if (empty($order)) {
            return fail('订单不存在', CODE_ORDER_NOT_EXISTS);
        }
        if ($order['status'] < 3) {
            $order['status'] = 3;
        } elseif ($order['status'] == 5) {
            $order['status'] = 4;
        }
        $order['order_id'] = strval($order['order_id']);
        if ($order['status'] == 10) {
            $order['settle_price'] = 0;
        } else {
            $order['settle_price'] = $order['sale_price'] - $order['profit'];
        }

        return success('查询成功', $order);
    }

    /**
     * 生成订单号
     */
    private function generateOrderId()
    {
        for ($i = 0; $i < 21; $i++) {
            $orderId = date('ymdHis') . str_pad(mt_rand(0, 999999), 6, STR_PAD_LEFT);
            $id = Db::name('movie_order')
                ->where('order_id', $orderId)
                ->value('id');
            if (empty($id)) {
                return $orderId;
            }
        }

        return false;
    }
}
